﻿/*******************************************************************
* Copyright(c)
* 文件名称: BLEManager.cs
* 简要描述:
* 创建日期: #CreateTime# 
* 作者: QianXi
* 邮箱: 2470460089@qq.com
******************************************************************/

using System;
using UnityEngine;

public class BLEManager
{
    #region 单例
    static BLEManager instance;
    private BLEManager()
    {

    }

    public static BLEManager Instance
    {
        get
        {
            if (instance == null)
            {
                instance = new BLEManager();
            }
            return instance;
        }
    }
    #endregion

    #region 蓝牙参数
    /// <summary>
    /// 系统是否开启蓝牙,调用BlueInit函数此参数会被赋值
    /// </summary>
    public bool SysBluetoothState = false;
    /// <summary>
    /// 是否连接到蓝牙
    /// </summary>
    public bool isConnectedBlue = false;
    //连接的蓝牙信息
    public BLEDeviceInfo ConnectedBlueInfo;

    //是否连接到音频蓝牙
    public bool isConnectA2DPBlue;
    //连接到的音频蓝牙信息
    public BLEDeviceInfo ConnectedA2DPBlueInfo;

    #endregion
    BLEMsgHandler bLEMsgHandler;

#if UNITY_ANDROID
    AndroidJavaObject jo;
#endif
    /// <summary>
    /// 蓝牙初始化,请求开启蓝牙
    /// </summary>
    public void BlueInit(Action BlueInitFinishEvent,bool isListenA2DP = false,Action<bool,BLEDeviceInfo> A2DPListener = null)
    {
        //挂载接收脚本
        GameObject BLEMsgReceiver = GameObject.Find("BLEMsgReceiver");
        if (BLEMsgReceiver == null)
            BLEMsgReceiver = new GameObject("BLEMsgReceiver");

        if (BLEMsgReceiver != null)
        {
            bLEMsgHandler = BLEMsgReceiver.GetComponent<BLEMsgHandler>();
            if (bLEMsgHandler == null)
                bLEMsgHandler = BLEMsgReceiver.AddComponent<BLEMsgHandler>();
        }
        this.A2DPListener = A2DPListener;
        GameObject.DontDestroyOnLoad(BLEMsgReceiver);

#if UNITY_ANDROID
        if (jo == null)
        {
            AndroidJavaClass javaClass = new AndroidJavaClass("com.qianxi.bleforunity.BLEForUnity");
            jo = javaClass.CallStatic<AndroidJavaObject>("GetInstance");
        }
        bLEMsgHandler.RegisterBLEInitFinish(BlueInitFinishEvent);
        if (jo != null)
            jo.Call("BlueInit", isListenA2DP);
#endif
    }
    /// <summary>
    /// 开启音频蓝牙的监听
    /// </summary>
    public void StartA2DPListen()
    {
        if (!Application.isEditor)
        {
#if UNITY_ANDROID
            if (jo != null)
                jo.Call("StartA2DPListen",true);
#endif
        }
    }
    /// <summary>
    /// 如果不需要监听只需判断当前音频蓝牙的连接,可使用此函数
    /// </summary>
    public void JudgeConAudioBlueA2DP()
    {
        if (!Application.isEditor)
        {
#if UNITY_ANDROID
            if (jo != null)
                jo.Call("JudgeConAudioBlueA2DP");
#endif
        }
    }
    public void StartScan(string[] serviceUUIDs = null,Action<BLEDeviceInfo> ScanEvent = null)
    {
        string serviceUUIDsString = "";
        if (serviceUUIDs != null)
        {
            serviceUUIDsString = serviceUUIDs.Length > 0 ? "" : null;
            foreach (string serviceUUID in serviceUUIDs)
                serviceUUIDsString += serviceUUID + "|";
        }
        this.ScanEvent = ScanEvent;
        if (!Application.isEditor)
        {
#if UNITY_ANDROID
            if (jo != null)
                jo.Call("StartScan", serviceUUIDsString);
#endif
        }
    }
    public void StopScan()
    {
        if (!Application.isEditor)
        {
#if UNITY_ANDROID
            if (jo != null)
                jo.Call("StopScan");
#endif
        }
    }
    public void ConnectBLEByName(BLEDeviceInfo bLEScanDeviceInfo, Action<bool> ConnectListener = null,
        Action<string> ServiceUUIDs = null,Action<CharacteristicInfo> CharacteristicUUIDs = null)
    {
        ConnectedBlueInfo = bLEScanDeviceInfo;
        this.ConnectListener = ConnectListener;
        if(bLEMsgHandler != null)
        {
            bLEMsgHandler.DiscoveyServiceUUID = ServiceUUIDs;
            bLEMsgHandler.CharacteristicUUID = CharacteristicUUIDs;
        }
        if (!Application.isEditor)
        {
#if UNITY_ANDROID
            if (jo != null)
                jo.Call("ConnectBLEByName", bLEScanDeviceInfo.DeviceName);
#endif
        }
    }
    public void ConnectBLEByAddress(BLEDeviceInfo bLEScanDeviceInfo, Action<bool> ConnectListener = null,
        Action<string> ServiceUUIDs = null, Action<CharacteristicInfo> CharacteristicUUIDs = null)
    {
        ConnectedBlueInfo = bLEScanDeviceInfo;
        this.ConnectListener = ConnectListener;
        if (bLEMsgHandler != null)
        {
            bLEMsgHandler.DiscoveyServiceUUID = ServiceUUIDs;
            bLEMsgHandler.CharacteristicUUID = CharacteristicUUIDs;
        }

        if (!Application.isEditor)
        {
#if UNITY_ANDROID
            if (jo != null)
                jo.Call("ConnectBLEByAddress", bLEScanDeviceInfo.MacAddress);
#endif
        }
    }
    public void ReadCharacteristic(CharacteristicInfo characteristicInfo, Action<bool, BLEDeviceInfo, string> ReadEvent)
    {
        ReadCharacteristic(characteristicInfo.bLEDeviceInfo.MacAddress,characteristicInfo.ServiceUUID, characteristicInfo.UUID, ReadEvent);
    }
    public void ReadCharacteristic(string MACAddress,string ServiceUUID,string CharacteristicUUID,Action<bool, BLEDeviceInfo, string> ReadEvent)
    {
        if (bLEMsgHandler != null)
        {
            bLEMsgHandler.ReadEvent = ReadEvent;
        }
        if (!Application.isEditor)
        {
#if UNITY_ANDROID
            if (jo != null)
                jo.Call("ReadCharacteristic", MACAddress, ServiceUUID, CharacteristicUUID);
#endif
        }
    }
    public void NotifyCharacteristic(CharacteristicInfo characteristicInfo, Action<bool, string> notifyEvent,
        Action<BLEDeviceInfo, string> notifyDataEvent)
    {
        NotifyCharacteristic(characteristicInfo.bLEDeviceInfo.MacAddress, characteristicInfo.ServiceUUID,
            characteristicInfo.UUID, notifyEvent, notifyDataEvent);
    }
    public void NotifyCharacteristic(string MACAddress, string ServiceUUID, string CharacteristicUUID,
        Action<bool, string> notifyEvent,Action<BLEDeviceInfo,string> notifyDataEvent)
    {
        if (bLEMsgHandler != null)
        {
            bLEMsgHandler.NotifyEvent = notifyEvent;
            bLEMsgHandler.NotifyDataEvent = notifyDataEvent;
        }
        if (!Application.isEditor)
        {
#if UNITY_ANDROID
            if (jo != null)
                jo.Call("SubscribeCharacteristic", MACAddress, ServiceUUID, CharacteristicUUID);
#endif
        }
    }
    public void UnNotifyCharacteristic(CharacteristicInfo characteristicInfo, Action<bool, string> notifyEvent)
    {
        UnNotifyCharacteristic(characteristicInfo.bLEDeviceInfo.MacAddress, characteristicInfo.ServiceUUID,
            characteristicInfo.UUID, notifyEvent);
    }
    public void UnNotifyCharacteristic(string MACAddress, string ServiceUUID, string CharacteristicUUID,
       Action<bool, string> notifyEvent)
    {
        if (bLEMsgHandler != null)
        {
            bLEMsgHandler.UnNotifyEvent = notifyEvent;
            bLEMsgHandler.NotifyEvent = null;
            bLEMsgHandler.NotifyDataEvent = null;
        }
        if (!Application.isEditor)
        {
#if UNITY_ANDROID
            if (jo != null)
                jo.Call("UnSubscribeCharacteristic", MACAddress, ServiceUUID, CharacteristicUUID);
#endif
        }
    }
    /// <summary>
    /// 写数据
    /// </summary>
    /// <param name="characteristicInfo"></param>
    /// <param name="writeEvent"></param>
    /// <param name="deltaTime">一次只能发送20字节,超20字节会分次发送,deltaTime为分次发送间的间隔,一般是20-40毫秒</param>
    public void WriteCharacteristic(CharacteristicInfo characteristicInfo, string SendData, Action<bool, string, string> writeEvent, int deltaTime = 30)
    {
        WriteCharacteristic(characteristicInfo.bLEDeviceInfo.MacAddress, characteristicInfo.ServiceUUID,
            characteristicInfo.UUID, SendData, writeEvent, deltaTime);
    }
    public void WriteCharacteristic(string MACAddress, string ServiceUUID, string CharacteristicUUID,string SendData,
     Action<bool, string,string> writeEvent, int deltaTime = 30)
    {
        if (bLEMsgHandler != null)
        {
            bLEMsgHandler.WriteEvent = writeEvent;
        }
        if (!Application.isEditor)
        {
#if UNITY_ANDROID
            if (jo != null)
                jo.Call("WriteCharacteristic", MACAddress, ServiceUUID, CharacteristicUUID, SendData, deltaTime);
#endif
        }
    }
    public void DisConnect()
    {
        if(isConnectedBlue)
        {
            DisConnect(ConnectedBlueInfo.MacAddress);
        }
    }
    public void DisConnect(string BLEName)
    {
        if (!Application.isEditor)
        {
#if UNITY_ANDROID
            if (jo != null)
                jo.Call("DisConnect", BLEName);
#endif
        }
    }
    public void BlueDeInit()
    {
        if (!Application.isEditor)
        {
#if UNITY_ANDROID
            if (jo != null)
                jo.Call("BlueDeInit");
#endif
        }
    }

    Action<BLEDeviceInfo> ScanEvent = null;
    public void AddScanDevice(string DeviceName, string MacAddress, string Rssi)
    {
        ScanEvent?.Invoke(new BLEDeviceInfo(DeviceName, MacAddress, Rssi));
    }

    Action<bool,BLEDeviceInfo> A2DPListener = null;
    public void A2DPListen(bool isConnect, BLEDeviceInfo A2DPInfo)
    {
        isConnectA2DPBlue = isConnect;
        ConnectedA2DPBlueInfo = A2DPInfo;
        A2DPListener?.Invoke(isConnect,A2DPInfo);
    }

    Action<bool> ConnectListener = null;
    public void BlueConnectStateListener(string state)
    {
        isConnectedBlue = state.Equals("1");
        if(!isConnectedBlue)
        {
            ConnectedBlueInfo = null;
        }
        ConnectListener?.Invoke(isConnectedBlue);
        ConnectListener = null;
    }
    public void GetNewBlueState()
    {
        if (!Application.isEditor)
        {
#if UNITY_ANDROID
            if (jo != null)
                jo.Call("GetNewBlueState");
#endif
        }
    }
    public void OnApplicationPause(bool focus)
    {
        if (!Application.isEditor)
        {
#if UNITY_ANDROID
            if (jo != null)
                jo.Call("ApplicationPause", focus);
#endif
        }
    }
}